Fancy Themes
This guide will show you how to use Fancy Themes.
#Examples
Themes serve as a powerful tool to transform the appearance and experience of components within an application. They are implemented through the use of the ThemeProvider
component. Each theme distinguishes itself by configuring a unique set of values for our design tokens, altering the visual characteristics of components. To explore all the available design tokens, refer to the Design Tokens page.
For a component to be adaptable to various themes, it needs to rely on design tokens dynamically rather than static values. This implies that the component's CSS should be crafted to allow for theming by utilizing var(--design-token-name)
declarations, which is known as "CSS custom properties" or "CSS variables". Consider the following example, showcasing how a component's CSS might be structured:
.box {
background-color: var(--color--background--static--secondary);
border: 1px solid var(--color--border--separator);
color: var(--color--text--static--body);
}
The ThemeProvider
supplies the values for these design tokens, thereby influencing the appearance of components. In cases where no specific theme is provided, the system resorts to using the default theme.
const boxStyle = {
width: "200px",
height: "100px",
display: "flex",
alignItems: "center",
justifyContent: "center",
backgroundColor: "var(--color--background--static--secondary)",
border: "1px solid var(--color--border--separator)",
color: "var(--color--text--static--body)",
};
return (
<Content flexDirection="row" gap="medium">
<ThemeProvider theme="default">
<div style={boxStyle}>Default Theme</div>
</ThemeProvider>
<ThemeProvider theme="dark">
<div style={boxStyle}>Dark Theme</div>
</ThemeProvider>
</Content>
);
Note: The ThemeProvider
component must be placed at the root of your application to ensure that all components have access to the active theme. The associated stylesheets of each theme are automatically injected into the document by the global.css
file (see Fancy Context page). However, if our global CSS file introduces conflicts with your existing styles, you can import only the themes.css
file, which contains the design-tokens styles for all themes.
@import "@siteimprove/fancylib/themes.css";
Alternativelly, you can manually import the associated stylesheet for each theme, as shown below:
@import "@siteimprove/fancylib/design-tokens/themes/default.css";
@import "@siteimprove/fancylib/design-tokens/themes/dark.css";
#Accessing the active theme
You can also use the useTheme
hook to access the current theme in your components. This is useful if you want to conditionally render components based on the active theme.
const ThemedContent = () => {
const activeTheme = useTheme();
return <div>{activeTheme === "dark" ? "Dark Theme" : "Default Theme"}</div>;
};
return (
<>
<ThemeProvider theme="default">
<ThemedContent />
</ThemeProvider>
<ThemeProvider theme="dark">
<ThemedContent />
</ThemeProvider>
</>
);
#Using design tokens programmatically
You can use the useDesignTokens
hook to access the current theme's design tokens. This is useful if you want to use the design tokens in your own components keeping your components in sync with the theme.
const ThemedText = ({ children }: { children: React.ReactNode }) => {
const { ColorTextStaticBody } = useDesignToken();
return <span style={{ color: ColorTextStaticBody }}>{children}</span>;
};
return (
<>
<ThemeProvider theme="default">
<ThemedText>Default Theme</ThemedText>
</ThemeProvider>
<ThemeProvider theme="dark">
<ThemedText>Dark Theme</ThemedText>
</ThemeProvider>
</>
);